<script setup lang="tsx">
import { ref, markRaw, onMounted, reactive, nextTick, watch } from 'vue'
import { useRoute } from 'vue-router'
import type { AxiosResponse } from 'axios'

import hljs from 'highlight.js'
import Vditor from 'vditor';
import 'vditor/dist/index.css';
import 'highlight.js/styles/github-dark.css';

import { HttpCodeEnum } from '@packages/share/enums'
import { getLoopholeInfoAPI, getDownloadAPI, getLoopXGPTINFOAPI } from '@/api/search/index'
import { ElMessage, ElDialog,vLoading } from 'element-plus'
import { useDownload } from '@/hooks/web'
import { Download, Clock, Aim, CircleCheck, View, Help } from '@element-plus/icons-vue'
import GaugeChart from './components/gaugeChart.vue'
import BaseTab from './components/loophole/baseInfoTab.vue'
import RiskTab from './components/loophole/riskTab.vue'
import AssetTab from './components/loophole/assetTab.vue'
import FixTab from './components/loophole/fixTab.vue'
import assetdetails from './components/loophole/asset-details.vue'
const route = useRoute()
const id = ref(`${route.params.id}`)
const risklevel = ref(`${route.params.risklevel}`)
const { handleDownload, downloadLoading } = useDownload(getDownloadAPI, id.value)
const activeName = ref('base')
const info = ref({})
const space = ref([])
// 详细页抽屉显示状态
const drawer = ref(false)
// 详细显示目标
const LoopValue = reactive({
  _item: {}
})
// Vditor盒子
const VRef = ref()
// Vditor实例
const vditorInstance = ref();
// loading状态
const loadFlag = ref(false)
// GPT抽屉状态
const XGPVisible = ref()
// GPT请求参数
const XGPTKEY = ref()
// GPT输出字符
const outStr = ref('')
// GPT正在执行(防止请求期间关闭dialog重新请求)
const IsGptFlag = ref(false)
// 详细点击事件
const DetailItem = (item: object) => {
  drawer.value = true
  LoopValue._item = item
}

const ICONENUM = ref({
  Clock: Clock,
  View: View,
  Help: Help,
  CircleCheck: CircleCheck,
  Aim: Aim
})
// 漏洞信息
const getInfo = (id: string) => {
  getLoopholeInfoAPI(id).then((res: AxiosResponse) => {
    const { data, code, message } = res.data
    if (code === HttpCodeEnum.SUCCESS) {
      info.value = data.info
      space.value = data.space
    } else ElMessage.error(message)
  })
  getLoopXGPTINFOAPI(id).then((res: AxiosResponse) => {
    const { data, code, message } = res.data
    if (code === HttpCodeEnum.SUCCESS) {
      data.desc = data.desc.replace(/[\r\n]/g, '')
      XGPTKEY.value = data
    } else ElMessage.error(message)
  })
}

const XGPT = () => {
  XGPVisible.value = true
  if (IsGptFlag.value === true) return
  loadFlag.value = true
  outStr.value = ''
  // if (outStr.value.length > 0) {
  //   return
  // }

  fetch(`cy/exploit/searchExploitGpt`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ ...XGPTKEY.value }) // 只传递一次参数
  })
    .then(async (response: any) => {
      const reader = response.body.getReader() // 读取流
      const decoder = new TextDecoder() // 处理流文本
      loadFlag.value = false
      IsGptFlag.value = true
      while (true) {
        const { done, value } = await reader.read()
        if (done) {
          console.log("传输完成!!!");
          break
        }
        let text = decoder.decode(value, { stream: true }).replace(/data:/g, '').replace(/(\[DONE\])?/g, '').trim();
        const contentMatch = text.match(/"content":"([^"]+)"/);//返回数据是字符串
        if (contentMatch && contentMatch[1]) {
          const contentValue = contentMatch[1].replace(/\\n/g, '\n').replace(/\\"/g, '"'); // 处理转义字符
          outStr.value += contentValue
          if (vditorInstance.value) {
            vditorInstance.value.setValue(outStr.value);
          }
        }

      }
    })
    .catch((error) => {
      console.error('连接错误:', error)
      loadFlag.value = false
    })
    .finally(() => {
      IsGptFlag.value = false
    })
}
const VitorInit = () => {
  nextTick(() => {
    if (VRef.value) {
      vditorInstance.value = new Vditor(VRef.value, {
        height: 450,
        value: outStr.value,
        cache: {
          enable: false,
          id: 'VditorValue',
        },
        preview: {
          hljs: {
            enable: true,
            style: "github-dark",
            lineNumber: true,
          }
        },
        toolbar: [],
        after: () => {
          console.log('Vditor is ready');
        },
      });
    }
  });
}
watch(XGPVisible, (newVal) => {
  if (newVal) {
    // 弹窗显示时初始化 Vditor
    nextTick(() => {
      VitorInit();
    });
  } else {
    // 弹窗关闭时销毁 Vditor
    if (vditorInstance.value) {
      vditorInstance.value.destroy();
      vditorInstance.value = null;
    }
  }
});




onMounted(() => {
  getInfo(id.value)
})
</script>

<template>
  <div class="jm-container jm-mainbox">
    <div class="jm-bg-color info-card">
      <div class="top flex-center">
        <div class="left">
          <GaugeChart v-model:id="id" :risklevel="Number(risklevel)" />
        </div>
        <div class="right">
          <div class="title">{{ info.title }}</div>
          <div class="infos">
            <jm-tag effect="plain" :type="Number(risklevel) > 2 ? 'danger' : Number(risklevel) < 2 ? 'primary' : 'warning'
              " class="tags">{{ info.type }}</jm-tag>
            <jm-tag class="XGPT" @click.stop="XGPT()">GPT解读</jm-tag>
            <jm-button class="report" type="info" round :icon="Download" :loading="downloadLoading"
              @click="handleDownload">漏洞资产报告</jm-button>
          </div>
        </div>
      </div>
      <div class="bottom">
        <div class="space flex-center">
          <div class="item" v-for="(item, index) in space" :key="index">
            <div class="icon">
              <jm-icon>
                <component :is="markRaw(ICONENUM[item.icon])" />
              </jm-icon>
            </div>
            <div class="desc">
              <div class="label">{{ item.label }}</div>
              <div>{{ item.value }}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="jm-bg-color tab-card">
      <jm-tabs v-model="activeName">
        <jm-tab-pane label="基本信息" name="base">
          <BaseTab v-if="activeName === 'base'" v-model:id="id" />
        </jm-tab-pane>
        <jm-tab-pane label="风险评估" name="risk">
          <RiskTab v-if="activeName === 'risk'" v-model:id="id" />
        </jm-tab-pane>
        <jm-tab-pane label="影响资产" name="asset">
          <AssetTab v-if="activeName === 'asset'" v-model:id="id" @detailItem="DetailItem" />
        </jm-tab-pane>
        <jm-tab-pane label="修复方案" name="fix">
          <FixTab v-if="activeName === 'fix'" v-model:id="id" />
        </jm-tab-pane>
      </jm-tabs>
    </div>
    <jm-drawer v-model="drawer" title="I am the title" :with-header="false">
      <assetdetails v-model:item="LoopValue._item" />
    </jm-drawer>
    <el-dialog class="GPTDialog" v-model="XGPVisible" :modal="true" title="漏洞解读">
      <div class="GPTBox">
        <!-- 头部显示 -->
        <div class="GPTNav flex">
          <span>漏洞编号：{{ XGPTKEY.cveId }}</span>
          <span>漏洞类型：{{ info.type }}</span>
          <span>厂商：{{ XGPTKEY.vendor }}</span>
          <span :class="Number(risklevel) < 2 ? 'lowrisk' : Number(risklevel) > 2 ? 'highrisk' : 'middlerisk'">漏洞等级：{{
            Number(risklevel) < 2 ? '低风险' : Number(risklevel) > 2 ? '高风险' : '中风险' }}</span>
        </div>
        <!-- loading -->
        <div class="XGPTLoading" v-loading="loadFlag" v-if="loadFlag"></div>
        <!-- 加载内容 -->
        <div class="XGPTText" ref="VRef" v-show="!loadFlag"></div>

      </div>
    </el-dialog>
  </div>
</template>

<style scoped lang="scss">
.GPTDialog {
  .GPTBox {
    width: 100%;
    height: 500px;
    overflow: hidden;
    padding: 0 1rem;

    .GPTNav {
      padding: 0 1.25rem;
      // border: 1px solid #EEE;
      height: 1.875rem;
      line-height: 1.875rem;
      font-weight: 700;
      font-size: 1.1rem;
      color: #333;

      span {
        padding: 0 .625rem;
      }

      .lowrisk {
        color: #578dc9;
      }

      .highrisk {
        color: #b84337;
      }

      .middlerisk {
        color: #e3c55f;
      }
    }

    .XGPTLoading {
      height: 100%;
      justify-content: center;
      align-items: center;
    }

    .XGPTText {
      white-space: pre-wrap;
      background-color: #f5f6f8;
      overflow: auto;

      :deep(strong) {
        font-weight: 600;
      }
    }
  }
}

.container {
  width: 100%;
  height: 88%;
  margin: 20px auto;
  font-family: Arial, sans-serif;
  overflow: auto;
}

.card {
  background: #fff;
  padding: 0 20px;
  border-radius: 8px;
  box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
  margin-bottom: 20px;
}

.flex-center {
  display: flex;
  align-items: center;
}

.jm-container {
  padding: 0;
}

.info-card {
  position: relative;

  .report {
    // position: absolute;
    // top: 6.25rem;
    // right: 0.625rem;
  }

  .top {
    height: 15.625rem;

    .left {
      width: 20%;
      height: 100%;

      .chart-content {
        height: 100%;
      }
    }

    .right {
      flex: 1;

      .title {
        margin-bottom: 0.625rem;
        font-size: 1.625rem;
        font-weight: 700;
      }

      .infos {
        margin-bottom: 0.625rem;

        .XGPT {
          color: #666;
          background-color: #eef3fc;
          margin-right: 0.5rem;
          border: 1px solid #eef3fc;
          border-radius: 0.3rem;
          font-size: 14px;
          line-height: 14px;
          cursor: pointer;

          &:hover {
            color: #0d7cf2;
          }
        }

        .tags {
          margin-right: 1.25rem;
        }
      }
    }
  }

  .bottom {
    width: 50%;
    padding-left: 5rem;
    padding-bottom: 1.25rem;

    .space {
      justify-content: space-between;

      .item {
        display: flex;

        .icon {
          margin-top: 0.1875rem;
          margin-right: 0.625rem;
        }

        .label {
          margin-bottom: 0.625rem;
        }
      }
    }
  }
}

.tab-card {
  padding: 0.625rem 1.25rem;
  margin-top: 0.625rem;
  min-height: 12.5rem;
}
</style>
